// 实现这个项目的构建任务

const del = require('del')
const browserSync = require('browser-sync')
const bs = browserSync.create()

const { src, dest, parallel, series, watch  } = require('gulp')
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
const sass = plugins.sass(require('sass'))

// 可作为统一配置对象对外暴露，以实现定制配置化
let config = {
  // 默认数据
  src: 'src',
  temp: 'temp',
  dist: 'dist',
  public: 'public',
  paths: {
    styles: 'assets/styles/*.scss',
    scripts: 'assets/scripts/*.js',
    pages: '*.html',
    images: 'assets/images/**',
    fonts: 'assets/fonts/**',
  }
}

// 注意：转换时，"_" 开头的文件会被忽略

// 转换 scss 文件
const style = () => {
  return src(config.paths.styles, { base: config.src, cwd: config.src })
    .pipe(sass()) // sass 转换
    .pipe(dest(config.temp)) // 输出
    .pipe(bs.reload({ stream: true })) // 改动监听
}

// 转换 js 文件
const script = () => {
  return src(config.paths.scripts, { base: config.src, cwd: config.src })
    .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
    .pipe(dest(config.temp))
    .pipe(bs.reload({ stream: true }))
}

// 转换 html 文件
const page = () => {
  return src(config.paths.pages, { base: config.src, cwd: config.src })
    .pipe(plugins.swig({ defaults: { cache: false } })) // 防止swig模板缓存导致页面不能及时更新
    .pipe(dest(config.temp))
    .pipe(bs.reload({ stream: true }))
}

// 压缩图片文件
const image = () => {
  return src(config.paths.images, { base: config.src, cwd: config.src })
    .pipe(plugins.imagemin())
    .pipe(dest(config.dist))
}

// 压缩字体文件
const font = () => {
  return src(config.paths.fonts, { base: config.src, cwd: config.src })
    .pipe(plugins.imagemin())
    .pipe(dest(config.dist))
}

// 处理其他文件
const other = () => {
  return src('**', { base: config.public, cwd: config.public })
    .pipe(dest(config.dist))
}

// 清理 temp、dist 目录
const clean = () => {
  return del([config.temp, config.dist])
}

// 启动服务运行项目
const serve = () => {

  // 实时监听文件变化，reload 更新页面
  watch(config.paths.styles, { cwd: config.src }, style)
  watch(config.paths.scripts, { cwd: config.src }, script)
  watch(config.paths.pages, { cwd: config.src }, page)
  watch(config.paths.images, { cwd: config.src }, bs.reload)
  watch(config.paths.fonts, { cwd: config.src }, bs.reload)
  watch('**', { cwd: config.public }, bs.reload)

  //初始化服务
  bs.init({
    server: {
      baseDir: [config.temp, config.src, config.public],
      routes: {
        '/node_modules': 'node_modules'
      }
    }
  })
}

// 压缩代码
const useref = () => {
  // 压缩代码
  return src(config.paths.pages, { base: config.temp, cwd: config.temp })
    .pipe(plugins.useref({ searchPath: [config.temp, '.'] }))
    .pipe(plugins.if(/\.js$/, plugins.uglify()))
    .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
    .pipe(plugins.if(/\.html$/, plugins.htmlmin({
      collapseWhitespace: true,
      minifyCSS: true,
      minifyJS: true
    })))
    .pipe(dest(config.dist))
}

// 编译任务
const compile = parallel(style, script, page)

//上线任务
const build = series(
  clean, 
  parallel(
    series(compile, useref), 
    image, 
    font, 
    other
  )
)

//开发任务
const develop = series(compile, serve)
    
module.exports = {
  clean,
  compile,
  serve,
  develop,
  build,
}